package com.ttcaca.cas.android.client;

import java.io.ByteArrayInputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URLEncoder;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Node;

import com.ttcaca.cas.android.client.model.LoginKey;
import com.ttcaca.cas.android.client.model.LoginResult;
import com.ttcaca.cas.android.client.model.User;
import com.ttcaca.cas.android.client.utils.Encoder;
import com.ttcaca.cas.android.client.utils.HttpUtils;

public class CasClient {

    private String casServer;

    private String service;

    private String pwd;

    private String corpid;

    private String tgc;

    public String getTgc() {
        return tgc;
    }

    public String getToken(String timestamp) throws UnsupportedEncodingException, NoSuchAlgorithmException {

        String token = Encoder.md5(corpid+timestamp+pwd);

        token = Encoder.urlEncode(token);

        return token;
    }

    public User login(String username,String password) throws Exception {

        LoginKey lk;

        try {
            lk = getLoginKey();
        } catch (Exception e) {
            e.printStackTrace();
            throw new Exception("CAS服务器getLoginKey发生异常");
        }

        LoginResult lr;

        try {
            lr =  getSt(username,password,lk);
        } catch (Exception e) {
            e.printStackTrace();
            throw new Exception("CAS服务器getSt发生异常");
        }

        if(!lr.isLogResult()){
            throw new Exception("用户名或密码错误");
        }

        String userinfo = "";

        try {
            userinfo = getUserInfo(lr.getSt());
        } catch (Exception e) {
            e.printStackTrace();
            throw new Exception("CAS服务器getUserInfo发生异常");
        }

        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        DocumentBuilder db = dbf.newDocumentBuilder();
        Document document = db.parse(new ByteArrayInputStream(userinfo.getBytes("UTF-8")));

        User user = new User();
        Node uid = document.getElementsByTagName("cas:uid").item(0).getFirstChild();
        Node userName = document.getElementsByTagName("cas:username").item(0).getFirstChild();
        Node realname = document.getElementsByTagName("cas:realname").item(0).getFirstChild();
        Node jobId = document.getElementsByTagName("cas:jobId").item(0).getFirstChild();
        Node jobName = document.getElementsByTagName("cas:jobName").item(0).getFirstChild();
        Node familyId = document.getElementsByTagName("cas:familyId").item(0).getFirstChild();
        Node familyName = document.getElementsByTagName("cas:familyName").item(0).getFirstChild();
        Node mobile = document.getElementsByTagName("cas:mobile").item(0).getFirstChild();
        Node email = document.getElementsByTagName("cas:email").item(0).getFirstChild();
        Node disable = document.getElementsByTagName("cas:disable").item(0).getFirstChild();
        Node createtime = document.getElementsByTagName("cas:createtime").item(0).getFirstChild();
        Node openid = document.getElementsByTagName("cas:openid").item(0).getFirstChild();

        if(uid!=null){user.setUid(uid.getNodeValue());}
        if(userName!=null){user.setUsername(userName.getNodeValue());}
        if(realname!=null){user.setRealname(realname.getNodeValue());}
        if(jobId!=null){user.setJobId(jobId.getNodeValue());}
        if(jobName!=null){user.setJobName(jobName.getNodeValue());}
        if(familyId!=null){user.setFamilyId(familyId.getNodeValue());}
        if(familyName!=null){user.setFamilyName(familyName.getNodeValue());}
        if(mobile!=null){user.setMobile(mobile.getNodeValue());}
        if(email!=null){user.setEmail(email.getNodeValue());}
        if(disable!=null){user.setDisable(disable.getNodeValue());}
        if(createtime!=null){user.setCreatetime(createtime.getNodeValue());}
        if(openid!=null){user.setOpenid(openid.getNodeValue());}

        return user;
    }

    public CasClient(String casServer, String service, String corpid, String pwd) {
        this.casServer = casServer;
        this.service = service;
        this.pwd = pwd;
        this.corpid = corpid;
    }

    private LoginKey getLoginKey() throws Exception {

        Date d = new Date();
        SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss");
        String timestamp = formatter.format(d);

        String params = "app=true&service="+service+"&timestamp="+timestamp+"&corpid="+corpid+"&token="+getToken(timestamp);

        HttpUtils utils = new HttpUtils();

        HttpURLConnection c = utils.sendRequest(casServer+"/login",params,"");

        String cookie = c.getHeaderField("Set-Cookie");

        //读取响应内容
        String response = utils.getResponse(c);

        if(response.contains("fail")){
            throw new Exception(response.split(" ")[1]);
        }

        LoginKey key = new LoginKey();
        key.setCookie(cookie.split(";")[0]);
        key.setLt(response.split(" ")[0]);
        key.setExecution(response.split(" ")[1]);
        return key;
    }

    private LoginResult getSt(String username,String password,LoginKey key) throws Exception {

        String params = "username=" + URLEncoder.encode(username)
                + "&password=" + URLEncoder.encode(password)
                + "&lt="+ URLEncoder.encode(key.getLt())
                + "&execution="+ URLEncoder.encode(key.getExecution())
                + "&submit=LOGIN&_eventId=submit"
                + "&service="+URLEncoder.encode(service);

        HttpUtils utils = new HttpUtils();

        HttpURLConnection c = utils.sendRequest(casServer+"/login",params,key.getCookie());

        LoginResult lr = new LoginResult();

        if(c.getHeaderField("Location")!=null && !c.getHeaderField("Location").equals("")){
            lr.setLogResult(true);
            lr.setSt(c.getHeaderField("Location").split("ticket=")[1]);

            String cookie = "";

            for(String cc : c.getHeaderFields().get("Set-Cookie")){
                if(cc.contains("TGC")){
                    cookie = cc;
                }
            }

            lr.setTgc(cookie);

            tgc = cookie.split(";")[0];
        }else{
            lr.setLogResult(false);
            return lr;
        }

        return lr;
    }

    private String getUserInfo(String st) throws Exception {

        String params = "service="+service+"&ticket="+st;

        HttpUtils utils = new HttpUtils();

        HttpURLConnection c = utils.sendRequest(casServer+"/serviceValidate",params,"");

        return utils.getResponse(c);
    }

    public boolean check(String tgc)throws Exception {

        HttpUtils utils = new HttpUtils();

        HttpURLConnection c = utils.sendRequest(casServer+"/login","",tgc);

        String sTotalString = utils.getResponse(c);

        if(sTotalString.contains("success")){
            System.out.println("成功登录");
            return true;
        }else{
            System.out.println("登录失败，可能是cookie超时");
            return false;
        }

    }
}
